package com.tuanzi.loan.web.bean.xhh.settlementsystem;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.starbaba.model.utils.JSONUtils;
import com.tuanzi.loan.business.constants.settlement.CompanyCooperationMode;
import com.tuanzi.loan.business.entity.CurrentUser;
import com.tuanzi.loan.business.entity.family.ProductInfo;
import com.tuanzi.loan.business.entity.system.Dictionary;
import com.tuanzi.loan.business.entity.system.SystemUser;
import com.tuanzi.loan.business.entity.xhh.settlementsystem.*;
import com.tuanzi.loan.business.service.settlementsystem.BillStatus;
import com.tuanzi.loan.business.service.xhh.settlementsystem.*;
import com.tuanzi.loan.core.aspect.Debug;
import com.tuanzi.loan.core.util.XLSUtils;
import com.tuanzi.loan.vo.request.xhh.settlementsystem.XhhSettlementIncomeRequest;
import com.tuanzi.loan.vo.response.xhh.settlementsystem.XhhSettlementIncomeResponse;
import com.tuanzi.loan.web.configuration.JSFListingBean;
import com.tuanzi.loan.web.lazy.xhh.settlementsystem.XhhSettlementIncomeLazyDataModel;
import com.tuanzi.loan.workflow.service.WorkflowManagerService;
import com.tuanzi.loan.workflow.service.WorkflowProcessorService;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.primefaces.event.FileUploadEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.faces.bean.ViewScoped;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.tuanzi.loan.business.constants.DictionaryCode.*;
import static java.math.BigDecimal.ROUND_HALF_DOWN;

/**
 * @author caiwanlin
 * @create 2018-08-16 20:30
 */
@Data
@Debug
@Component
@ViewScoped
@EqualsAndHashCode(callSuper = true)
public class XhhSettlementIncomeListBean extends JSFListingBean<XhhSettlementIncomeRequest, XhhSettlementIncomeResponse> {

	private static final long serialVersionUID = -7208461820787825224L;

	@Autowired
	private XhhSettlementCompanyService xhhSettlementCompanyService;

	@Autowired
	private XhhSettlementProductService xhhSettlementProductService;

	@Autowired
	private XhhSettlementIncomeService xhhSettlementIncomeService;

	@Autowired
	private XhhSettlementIncomeActivityService xhhSettlementIncomeActivityService;

	@Autowired
	private XhhSettlementBillService xhhSettlementBillService;

	@Autowired
	private WorkflowManagerService workflowManagerService;

	@Autowired
	private WorkflowProcessorService workflowProcessorService;

	private List<XhhSettlementProduct> productList;

	private List<XhhSettlementCompany> companyList;

	private List<ProductInfo> activityList;// 活动列表

	private XhhSettlementIncome settlementIncome;// 新增消耗记录

	private List<Long> activityIdList; // 关联的活动id

	private List<XhhSettlementIncomeResponse> selectIncomeList;// 记录选择的消耗记录

	private XhhSettlementBill settlementBill;// 开票

	private List<SystemUser> checkList;// 财务核查人

	private String PROCESS_DEF_KEY = "XhhBillSystem";// 流程定义key

	private String header = "新增";

	private Boolean isSpecialChannel = false; // 特殊推广渠道

	private Double rangeTotalIncomeAmount;

	private Double rangeTotalUvValue;

	private List<Integer> specialChannels;

	@PostConstruct
	public void init() throws Exception {
		companyList = xhhSettlementCompanyService.getCompanyList();
		productList = xhhSettlementProductService.getProductList();
		activityList = xhhSettlementProductService.getActivityList();
		activityIdList = Lists.newArrayList();
		settlementIncome = new XhhSettlementIncome();
		settlementBill = new XhhSettlementBill();
		initSpecialChannels();
		initLazyDataModel();
		loadTotal();
	}

	private void initSpecialChannels() {
		specialChannels = Lists.newArrayList();
		Dictionary dic = dictionaryService.findByCode(XHH_SETTLEMENT_SPECIAL_SPREAD_CHANNEL);
		if (null != dic) {
			specialChannels = Arrays.stream(dic.getValue1().split(",")).map(Integer::valueOf).collect(Collectors.toList());
		}
	}

	private void initLazyDataModel() throws Exception {
		Date now = new Date();
		$ = new XhhSettlementIncomeRequest();
		$.setStartTime(now);
		$.setEndTime(now);
		lazyDataModel = new XhhSettlementIncomeLazyDataModel($);
	}

	private void loadTotal() {
		rangeTotalIncomeAmount = xhhSettlementIncomeService.sumRangeTotalAmount($);
		rangeTotalUvValue = xhhSettlementIncomeService.sumRangeTotalUvValue($);
	}

	public Double getAverageUvValue() {
		if (0 == rangeTotalUvValue.doubleValue()) {
			return 0.0d;
		}

		return new BigDecimal(rangeTotalIncomeAmount).divide(new BigDecimal(rangeTotalUvValue), 2, ROUND_HALF_DOWN).doubleValue();
	}

	public void onReset() throws Exception {
		initLazyDataModel();
		onSearch();
	}

	public void onSearch() {
		loadTotal();
	}

	public void onBill() {
		// 是否选择消耗记录
		if (selectIncomeList == null || selectIncomeList.isEmpty()) {
			addErrorMessage("请选择消耗记录");
			return;
		}
		// 判断是否选的未开票的记录
		long count = selectIncomeList.parallelStream().filter(s -> {
			return s.getBillStatus() != BillStatus.NO_BILL.index;
		}).count();
		if (count > 0) {
			addErrorMessage("请选择未开票的记录");
			return;
		}
		// 判断是否选择同一主体开票
		Map<Long, List<XhhSettlementIncomeResponse>> collect = selectIncomeList.parallelStream().collect(Collectors.groupingBy(XhhSettlementIncomeResponse::getCompanyId));
		if (collect.size() > 1) {
			addErrorMessage("请选择同一个主体开票");
			return;
		}

		// 查询主体
		XhhSettlementIncomeResponse settlementIncomeResponse = selectIncomeList.get(0);
		XhhSettlementCompany settlementCompany = xhhSettlementCompanyService.findOne(settlementIncomeResponse.getCompanyId());
		// 开票金额
		Double incomeAmount = selectIncomeList.parallelStream().map(s -> s.getIncomeAmount()).collect(Collectors.summingDouble(s -> s));

		// 构造发票实体
		settlementBill = xhhSettlementBillService.structureSettlementBill(settlementCompany);
		settlementBill.setBillAmount(incomeAmount);
		// 记录类型(消耗)
		settlementBill.setRecordType(XhhRemainType.EXPEND.index);

		checkList = workflowManagerService.findFirstActivitySystemUserProcDefKey(PROCESS_DEF_KEY);
		execute("PF('billing').show();");
		update("incomeForm:bill-dialog");
	}

	public void onSaveBill() {
		String result = xhhSettlementBillService.validateBill(settlementBill);
		if (StringUtils.isNotBlank(result)) {
			addErrorMessage(result);
			return;
		}

		// 保存
		String checkName = checkList.parallelStream().filter(s -> s.getAccount().equals(settlementBill.getCheckAccount())).map(s -> s.getName()).findFirst().get();

		settlementBill.setCheckName(checkName);// 审核人姓名
		List<Long> ids = selectIncomeList.parallelStream().map(s -> (Long) s.getId()).collect(Collectors.toList());
		settlementBill.setDetailList(JSONUtils.toJsonString(selectIncomeList));// 保存此时刻的明细快照
		xhhSettlementBillService.onSave(settlementBill, ids);
		selectIncomeList = Lists.newArrayList();

		// 启动流程
		String account = CurrentUser.get().getAccount();
		String assignee = settlementBill.getCheckAccount();
		String title = "(熊花花)【" + settlementBill.getCompanyName() + "】消耗开票流程";
		List<String> businessKeys = Lists.newArrayList(settlementBill.getId().toString());
		Map<String, Object> variables = Maps.newHashMap();
		workflowProcessorService.startProcess(account, assignee, PROCESS_DEF_KEY, title, businessKeys, variables);

		addSuccessfullyMessage();
		execute("PF('billing').hide();");
		update("incomeForm");
	}

	/**
	 * 选择产品回显数据
	 */
	public void onSelectProduct() {
		Long productId = settlementIncome.getProductId();
		if (productId == null) {
			settlementIncome = new XhhSettlementIncome();
			activityIdList = Lists.newArrayList();
			return;
		}
		XhhSettlementProduct settlementProduct = xhhSettlementProductService.findOne(productId);
		convertIncome(settlementProduct);
	}

	private void convertIncome(XhhSettlementProduct settlementProduct) {
		settlementIncome = new XhhSettlementIncome();
		settlementIncome.setProductId(settlementProduct.getId());
		settlementIncome.setCompanyId(settlementProduct.getCompanyId());
		settlementIncome.setProductName(settlementProduct.getProductName());
		settlementIncome.setSpreadMode(settlementProduct.getSpreadMode());
		settlementIncome.setSpreadChannel(settlementProduct.getSpreadChannel());
		settlementIncome.setCopMode(settlementProduct.getCopMode());
		settlementIncome.setIncomeType(settlementProduct.getIncomeType());
		settlementIncome.setPriceCpa(settlementProduct.getPriceCpa());
		settlementIncome.setPriceCps(settlementProduct.getPriceCps());
		settlementIncome.setSettlementMode(settlementProduct.getSettlementMode());
		getActivityIds(settlementProduct);

		if (null == settlementIncome.getSpreadMode()) {
			settlementIncome.setSpreadMode(2);
		}

		if (null == settlementIncome.getSpreadChannel()) {
			settlementIncome.setSpreadChannel(0);
		}
	}

	private void getActivityIds(XhhSettlementProduct settlementProduct) {
		// 关联活动回显
		String activityIdStr = settlementProduct.getActivityIdStr();
		if (StringUtils.isNotBlank(activityIdStr)) {
			String[] split = activityIdStr.split(",");
			activityIdList = Arrays.asList(split).stream().map(Long::parseLong).collect(Collectors.toList());
		}
	}

	public void onChangeSpreadChannel() {
		isSpecialChannel = false;
		if (inSpecialChannel(settlementIncome.getSpreadChannel())) {
			activityIdList = Lists.newArrayList();
			isSpecialChannel = true;
		} else {
			if (null != settlementIncome.getProductId()) {
				XhhSettlementProduct settlementProduct = xhhSettlementProductService.findOne(settlementIncome.getProductId());
				getActivityIds(settlementProduct);
			}
		}
	}

	private boolean inSpecialChannel(int channel) {
		// 公众号 外推 短信 菠萝贷 快刻周转 推广渠道
		return specialChannels.stream().anyMatch(specialChannel -> specialChannel.equals(channel));
	}

	/**
	 * 保存记录
	 */
	public void onSave() {
		boolean validate = validate();
		if (validate == false)
			return;

		// 根据合作模式清除不需要的数据
		Integer copMode = settlementIncome.getCopMode();
		clearNotUserData(copMode);

		// 获取公司名称
		// String companyName = companyList.parallelStream().filter(c -> {
		// if (c.getId() == settlementIncome.getCompanyId()) return true;
		// return false;
		// }).map(s -> s.getCompanyName()).findFirst().get();
		XhhSettlementCompany con = xhhSettlementCompanyService.findOne(settlementIncome.getCompanyId());
		if (con == null) {
			addErrorMessage("查询不到公司");
			return;
		}
		String companyName = con.getCompanyName();
		settlementIncome.setCompanyName(companyName);
		xhhSettlementIncomeService.onSave(settlementIncome, activityList, activityIdList, isSpecialChannel);
		addSuccessfullyMessage();
		execute("PF('adding').hide();");
		update("incomeForm");
	}

	public boolean validate() {
		if (settlementIncome.getProductId() == null) {
			addErrorMessage("没有选择产品");
			return false;
		}
		if (settlementIncome.getCompanyId() == null) {
			addErrorMessage("没有选择主体");
			return false;
		}
		if (settlementIncome.getCopMode() == null) {
			addErrorMessage("没有选择合作模式");
			return false;
		}
		if (settlementIncome.getSpreadMode() == null) {
			addErrorMessage("没有选择推广方式");
			return false;
		}
		if (settlementIncome.getSpreadChannel() == null) {
			addErrorMessage("没有选择推广渠道");
			return false;
		}
		if (settlementIncome.getSettlementMode() == null) {
			addErrorMessage("没有选择结算模式");
			return false;
		}
		if (settlementIncome.getIncomeType() == null) {
			addErrorMessage("没有选择收入类型");
			return false;
		}
		if (settlementIncome.getStartTime() == null) {
			addErrorMessage("没有选择开始日期");
			return false;
		}
		if (settlementIncome.getEndTime() == null) {
			addErrorMessage("没有选择结束日期");
			return false;
		}

		if (settlementIncome.getStartTime().compareTo(settlementIncome.getEndTime()) > 0) {
			addErrorMessage("起始日期大于结束日期");
			return false;
		}

		if (settlementIncome.getIncomeAmount() == null) {
			addErrorMessage("结算金额不能为空");
			return false;
		}
		// 公众号推广渠道的允许没有关联活动
		if (CollectionUtils.isEmpty(activityIdList) && !isSpecialChannel) {
			addErrorMessage("没有关联活动");
			return false;
		}
		return true;
	}

	public void onAdd() {
		header = "新增";
		isSpecialChannel = false;
		settlementIncome = new XhhSettlementIncome();
		activityIdList = Lists.newArrayList();
	}

	public void onAdd(String id) {
		header = "新增";
		isSpecialChannel = false;
		settlementIncome = new XhhSettlementIncome();
		settlementIncome.setSpreadMode(2);
		settlementIncome.setSpreadChannel(0);
		activityIdList = Lists.newArrayList();
		if (StringUtils.isNotBlank(id)) {
			settlementIncome.setProductId(Long.valueOf(id));
			onSelectProduct();
		}
	}

	public void onSee(Long id) {
		header = "编辑";
		settlementIncome = xhhSettlementIncomeService.findOne(id);
		List<XhhSettlementIncomeActivity> byIncomeId = xhhSettlementIncomeActivityService.findAllByIncomeId(id);
		activityIdList = byIncomeId.stream().map(sa -> sa.getActivityId()).collect(Collectors.toList());
	}

	public void onDelete(Long id, Integer billStatus) {
		if (null == billStatus || !billStatus.equals(0)) {
			addErrorMessage("不能删除已开票的记录");
			return;
		}

		xhhSettlementIncomeService.onDelete(id);
		addSuccessfullyMessage();
	}

	/**
	 * 改变合作模式监听
	 */
	public void onChangeCopMode() {
		convertSelectActivityIds();
	}

	/**
	 * 监听结算金额
	 */
	public void onChangeIncomeAmount() {
		Integer copMode = settlementIncome.getCopMode();
		if (copMode == null) {
			return;
		}
		Double priceCpa = settlementIncome.getPriceCpa();
		Double priceCps = settlementIncome.getPriceCps();
		Integer registerCount = settlementIncome.getRegisterCount();
		Double lendAmount = settlementIncome.getLendAmount();
		Integer clickCount = settlementIncome.getClickCount();
		if (copMode == CompanyCooperationMode.CPA.index) {
			if (priceCpa != null && registerCount != null) {
				settlementIncome.setIncomeAmount(priceCpa * registerCount);
			} else {
				settlementIncome.setIncomeAmount(null);
			}
		} else if (copMode == CompanyCooperationMode.CPS.index) {
			if (priceCps != null && lendAmount != null) {
				settlementIncome.setIncomeAmount((priceCps * lendAmount) / 100);
			} else {
				settlementIncome.setIncomeAmount(null);
			}
		} else if (copMode == CompanyCooperationMode.CPC.index) {
			if (priceCpa != null && clickCount != null) {
				settlementIncome.setIncomeAmount(priceCpa * clickCount);
			} else {
				settlementIncome.setIncomeAmount(null);
			}
		} else if (copMode == CompanyCooperationMode.CPA_CPS.index) {
			if (priceCpa != null && priceCps != null && registerCount != null && lendAmount != null) {
				settlementIncome.setIncomeAmount((priceCpa * registerCount) + (priceCps * lendAmount / 100));
			} else {
				settlementIncome.setIncomeAmount(null);
			}
		}
	}

	public void onChangeParticipateUv() {
		Date startTime = settlementIncome.getStartTime();
		Date endTime = settlementIncome.getEndTime();
		settlementIncome.setEndTime(startTime);
		if (startTime == null || endTime == null)
			return;
		if (activityIdList == null || activityIdList.isEmpty())
			return;
		if (startTime.compareTo(endTime) > 0) {
			addErrorMessage("起始日期大于结束日期");
			return;
		}
		Integer uv = xhhSettlementIncomeActivityService.getUv(startTime, endTime, activityIdList);
		settlementIncome.setParticipateUv(uv);
	}

	/**
	 * 根据合作模式清空不需要的数据
	 *
	 * @param copMode
	 */
	public void clearNotUserData(Integer copMode) {
		if (copMode == null) {
			convertSelectActivityIds();
			return;
		}
		if (copMode == CompanyCooperationMode.CPA.index) {
			settlementIncome.setPriceCps(null);
			settlementIncome.setLendAmount(null);
			settlementIncome.setClickCount(null);
		} else if (copMode == CompanyCooperationMode.CPS.index) {
			settlementIncome.setPriceCpa(null);
			settlementIncome.setRegisterCount(null);
			settlementIncome.setClickCount(null);
		} else if (copMode == CompanyCooperationMode.CPC.index) {
			settlementIncome.setPriceCps(null);
			settlementIncome.setRegisterCount(null);
			settlementIncome.setLendAmount(null);
		} else if (copMode == CompanyCooperationMode.CPA_CPS.index) {
			settlementIncome.setClickCount(null);
		}
	}

	public void convertSelectActivityIds() {
		ArrayList<Long> temp = new ArrayList<>();
		for (Object a : activityIdList) {
			temp.add(Long.parseLong((String) a));
		}
		activityIdList = temp;
	}

	public void postProcessXLS(Object doc) {
		HSSFWorkbook wb = (HSSFWorkbook) doc;
		XLSUtils.convertStringToNumeric(wb);
	}

	public void onUploadAttachment(FileUploadEvent event) {
		settlementBill.setAttachmentUrl(this.uploadImg(event.getFile()));
		addInfoMessage("上传成功");

	}

	public void onUploadImgAttachment(FileUploadEvent event) {
		settlementBill.setImgAttachmentUrl(this.uploadImg(event.getFile()));
		addInfoMessage("上传成功");

	}

	public void onDeleteAttachment(String type) {
		if (StringUtils.isBlank(type)) {
			settlementBill.setAttachmentUrl(null);
		} else {
			settlementBill.setImgAttachmentUrl(null);
		}
		addInfoMessage("删除成功");
	}

	@Override
	protected List<String> getDictionaryCodes() {
		return Lists.newArrayList(XHH_SETTLEMENT_SPREAD_CHANNEL, XHH_SETTLEMENT_INCOME_TYPE, XHH_SETTLEMENT_SPREAD_MODE,
				XHH_COOPERATION_MODE, XHH_SETTLEMENT_CYCLE, XHH_SETTLEMENT_BILLING_CONTENT,
				XHH_SETTLEMENT_BILL_TYPE);
	}
}
